package com.focusai.efairy.network.request.base;

import android.support.annotation.CallSuper;
import android.support.annotation.WorkerThread;

import com.focusai.efairy.network.NetworkResponse;
import com.focusai.efairy.network.Response;
import com.focusai.efairy.network.exception.NetworkException;
import com.focusai.efairy.network.exception.ParseException;
import com.focusai.efairy.network.exception.ServerException;
import com.focusai.efairy.utils.ErrorCodeUtils;
import com.focusai.efairy.utils.StringUtils;
import com.focusai.efairy.utils.log.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by heqingbao on 2016/8/3.
 */
public abstract class Request<T> {
    private static final String TAG = Request.class.getSimpleName();

    public interface Method {
        int GET = 0;
        int POST = 1;
        int PUT = 2;
        int DELETE = 3;
        int HEAD = 4;
        int OPTIONS = 5;
        int TRACE = 6;
        int PATCH = 7;
    }

    private int mMethod;
    private String mUrl;

    private Response.Listener<T> mListener;

    private boolean mCanceled;

    private Object mTag;

    public Request(int method, String url, Response.Listener<T> listener) {
        mMethod = method;
        mUrl = url;
        mListener = listener;
    }

    public Request(int method, Response.Listener<T> listener) {
        mMethod = method;
        mListener = listener;
        mUrl = initUrl();
    }

    protected String initUrl() {
        throw new IllegalArgumentException("initUrl method must be override by subclass!");
    }

    public int getMethod() {
        return mMethod;
    }

    public String getUrl() {
        return mUrl;
    }

    public void setTag(Object tag) {
        mTag = tag;
    }

    @CallSuper
    public Map<String, String> getHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.put("version","1.3");//之前是1.2;API接口升级到1.3版本； HTTP协议请求头里面的version版本改为1.3
//        headers.put("Accept-Encoding", "identity");
//        headers.put("Connection", "close");
        return headers;
    }

    public Map<String, String> getParams() throws JSONException {
        return params == null ? new HashMap<String, String>() : params;
    }

    public Map<String, String> params;

    public void addParam(String key, String value) {
        if (params == null) {
            params = new HashMap<>();
        }
        params.put(key, value);
    }

    public void deliverResponse(T response) {
        if (mListener != null) {
            mListener.success(mTag, response);
        }
    }

    public void deliverError(NetworkException error) {
        if (mListener != null) {
            mListener.fail(mTag, error);
        }
    }

    public void finish() {
        mListener = null;
    }

    public void cancel() {
        mCanceled = true;
    }

    public boolean isCanceled() {
        return mCanceled;
    }

    protected boolean needOpenTokenInHeader() {
        return true;
    }

    @WorkerThread
    public Response<T> parseNetworkResponse(NetworkResponse networkResponse) {
        Log.D(TAG,"请求成功，开始解析结果");
        try {
            String result = new String(networkResponse.getData(), "UTF-8");

            Log.D(TAG,"============================efairy=======================" + result);

            parseExtras(result);

            if (handleRawResultData()) {
                T obj = parse(result);
                return Response.success(obj);
            }

            JSONObject jsonObject = new JSONObject(result);
            int errorCode = jsonObject.optInt("err_code");

            String errorMsg = null;
            if (jsonObject.has("error")) {
                errorMsg = jsonObject.getString("error");
            } else if (jsonObject.has("msg")) {
                errorMsg = jsonObject.getString("msg");
            }

//            if (errorCode != 200 && StringUtils.isStickBlank(errorMsg)) {
//                errorMsg = "服务器返回未知错误！";
//            }

            if (errorCode != 200) {
//                throw new ServerException(errorCode, errorMsg);
//                throw new ServerException(errorCode, StringUtils.isStickBlank(errorMsg) ? ErrorCodeUtils.getErrorMsgByCode(errorCode) : Base64Utils.decodeStr(errorMsg));
                throw new ServerException(errorCode, StringUtils.isStickBlank(errorMsg) ? ErrorCodeUtils.getErrorMsgByCode(errorCode) : errorMsg);
            }

            String dataJson = jsonObject.isNull("result") ? "" : jsonObject.optString("result");
            T obj = parse(dataJson);
            Log.D(TAG,"解析结果成功：" + (obj == null ? "Void" : obj.getClass().getSimpleName()));
            return Response.success(obj);
        } catch (ParseException e) {
            Log.E(TAG,"解析结果失败：", e);
            return Response.error(e);
        } catch (ServerException e) {
            Log.E(TAG,"服务端返回失败：errorCode=" + e.getErrorCode() + "errorMsg=" + e.getErrorMessage());
            return Response.error(e);
        } catch (Exception e) {
            Log.E(TAG,"处理数据失败：", e);
            return Response.error(new NetworkException(e));
        }
    }

    protected void parseExtras(String result) throws ParseException {
    }

    /**
     * 目前接口可能有多种返回格式：
     * 1. {"success":true,"error":null,"errorCode":100,"data":null}
     * 2. 直接是字符串或者JSON格式的数组
     *
     * @return true: 第1种格式；否则第2种格式。默认第1种格式
     */
    @WorkerThread
    protected boolean handleRawResultData() {
        return false;
    }

    /**
     * @param result result的结构可能是json字符串，也可能是其它。参考 parseNetworkResponse和handleRawResultData的逻辑
     * @return
     * @throws ParseException
     */
    @WorkerThread
    protected abstract T parse(String result) throws ParseException;

}
